package com.yanqu.road.server.gameplayer.module.activity.tomb;

import com.yanqu.road.entity.activity.*;
import com.yanqu.road.entity.config.patrons.PatronsInfo;
import com.yanqu.road.entity.enums.eActivityType;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.player.UserPatrons;
import com.yanqu.road.entity.union.activitygroup.UnionActivityGroup;
import com.yanqu.road.entity.union.activitygroup.UnionActivityGroupUnion;
import com.yanqu.road.entity.union.activitygroup.UnionActivityGroupUser;
import com.yanqu.road.logic.activity.tomb.config.TombConfig;
import com.yanqu.road.logic.activity.tomb.config.entity.ActivityTombRepair;
import com.yanqu.road.logic.bussiness.player.UserActivityBussiness;
import com.yanqu.road.logic.bussiness.player.UserBussiness;
import com.yanqu.road.logic.bussiness.player.UserPatronsBussiness;
import com.yanqu.road.logic.bussiness.servercenter.ActivityBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.pb.tomb.Tomb;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.game.service.GameService;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.tomb.service.*;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.config.GoodsMgr;
import com.yanqu.road.server.manger.config.PatronsMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.manger.union.GameUnionActivityGroupMgr;
import com.yanqu.road.server.protocol.CrossProtocol;
import com.yanqu.road.server.protocol.GameProtocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigInteger;
import java.util.*;

public class TombMgr extends TempMgr {
    private static Logger logger = LogManager.getLogger(TombMgr.class.getName());

    private static ActivityInfo activityInfo;

    private static TombConfig config;


    public static void reloadActivityData() {
        loadActivityData();

        long now = System.currentTimeMillis() / 1000;
        for (ActivityInfo allActivityInfo : ActivityMgr.getAllActivityInfos()) {
            if (allActivityInfo.getType() != eActivityType.Tomb.getValue()) {
                continue;
            }
            if (now > allActivityInfo.getEndShowTime()) {
                continue;
            }
            Tomb.TombActivityReloadReq.Builder builder = Tomb.TombActivityReloadReq.newBuilder();
            builder.setActivityId(allActivityInfo.getActivityId());
            GamePlayerMgr.sendToActivityCrossServerForUnionGroup(0, CrossProtocol.C_TOMB_ACTIVITY_RELOAD, allActivityInfo.getActivityId(), builder, null);
            break;
        }
    }

    public static void loadActivityData() {
        logger.info("加载tomb活动配置");
        long serverId = GameServer.getInstance().getServerId();

        List<ActivityInfo> activityInfoList = NormalActivityMgr.getOpenActivityInfoList(eActivityType.Tomb.getValue());
        if (activityInfoList.isEmpty()) {
            logger.info("服务器id:{}, 没有配置tomb活动", serverId);
            activityInfo = null;
            return;
        }
        activityInfo = activityInfoList.get(0);

        List<Integer> list = new ArrayList<>();
        list.add(activityInfo.getActivityId());
        Map<Integer, Map<String, ActivityConfig>> activityConfigMap = ActivityBussiness.getActivityConfigMap(list);
        Map<Integer, List<ActivityTableExt>> activityTableExtMap = ActivityBussiness.getActivityTableExtMap(list);
        config = new TombConfig(activityConfigMap.get(activityInfo.getActivityId()), activityTableExtMap.get(activityInfo.getActivityId()));
        config.setRepairItemProgress(GoodsMgr.getGoodsById(config.getConfig().getTOMB_REPAIR_ITEM_ID()).getParamList().get(0).intValue());
        logger.info("加载tomb活动配置完成，activityId: {}", activityInfo.getActivityId());

        getLogger().info("reload TombActivity end, activity {}", activityInfo.getActivityId());

    }

    /**
     * 获取使用道具数量上限，-1为不限制
     * @param goodsId 道具id
     */
    public static long getShowLimitedUseNum(int goodsId) {
        if (config == null || config.getConfig() == null) {
            return -1;
        }
        for (Property property : config.getConfig().getSHOW_LIMITED_USE_ITEM_NUM()) {
            for (Map.Entry<Integer, BigInteger> entry : property.getGoods().entrySet()) {
                if (entry.getKey() == goodsId) {
                    return entry.getValue().longValue();
                }
            }
        }
        return -1;
    }

    @Override
    public boolean init() throws Exception {
        this.reloadConfig();
        return true;
    }

    @Override
    public boolean reloadConfig() throws Exception {
        loadActivityData();

        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }

    public static ActivityInfo getActivityInfo() {
        return activityInfo;
    }

    public static TombConfig getConfig() {
        return config;
    }


    public static Tomb.PartnerTemp.Builder patronAbilityCorrection(UserPatrons userPatrons) {
        List<Integer> limitParam = TombMgr.getConfig().getConfig().getTOMB_PATRONS_ABILITY_LIMIT_PARAM();
        double p1 = limitParam.get(0);
        double p2 = limitParam.get(1);
        double p3 = limitParam.get(2);
        double p4 = limitParam.get(3);
        double p5 = limitParam.get(4);
        double p6 = limitParam.get(5);
        double p7 = limitParam.get(6);
        Tomb.PartnerTemp.Builder temp = Tomb.PartnerTemp.newBuilder();
        temp.setId(userPatrons.getPatronsId());
        double ability = userPatrons.getAbility().doubleValue();
        if (ability <= p4) {
            double step1 = ability / p5;
            double step2 = Math.log(step1);
            double step3 = step2 * p6;
            double step4 = Math.max(step3, p7);
            temp.setBaseEarn((int) step4);
        } else {
            double step1 = ability / p1;
            double step2 = Math.log(step1);
            double step3 = step2 * p2;
            double step4 = Math.max(step3, p3);
            temp.setBaseEarn((int) step4);
        }
        return temp;
    }


    public static List<Tomb.UserAbilityTemp> findTopPatrons(int activityId, int groupId) {

        //根据活动和玩家分组过滤玩家能力
        List<Long> userList = getGroupUserList(activityId, groupId);

        List<Tomb.UserAbilityTemp> list = new ArrayList<>();
        List<UserPatrons> patronsList = UserPatronsBussiness.getUserPatronsList(new ArrayList<>());
        Map<Long, List<UserPatrons>> userPatronListMap = new HashMap<>();
        for (UserPatrons userPatrons : patronsList) {
            if(userList.size() != 0 && !userList.contains(userPatrons.getUserId())){
                continue;
            }
            if (!userPatronListMap.containsKey(userPatrons.getUserId())) {
                userPatronListMap.put(userPatrons.getUserId(), new ArrayList<>());
            }
            userPatronListMap.get(userPatrons.getUserId()).add(userPatrons);
        }

        int jobPatronsLimit = TombMgr.getConfig().getConfig().getTOMB_JOB_PATRONS_LIMIT();
        for (List<UserPatrons> userPatrons : userPatronListMap.values()) {
            Map<Integer, List<UserPatrons>> occupationMap = new HashMap<>();

            for (UserPatrons userPatron : userPatrons) {
                PatronsInfo patronsInfo = PatronsMgr.getPatronsInfo(userPatron.getPatronsId());
                if (!occupationMap.containsKey(patronsInfo.getOccupation())) {
                    occupationMap.put(patronsInfo.getOccupation(), new ArrayList<>());
                }
                occupationMap.get(patronsInfo.getOccupation()).add(userPatron);
            }
            Tomb.UserAbilityTemp.Builder userAbilityTemp = Tomb.UserAbilityTemp.newBuilder();
            userAbilityTemp.setUserId(userPatrons.get(0).getUserId());
            userAbilityTemp.setServerId(GameServer.getInstance().getServerId());
            for (List<UserPatrons> userPatronsList : occupationMap.values()) {
                userPatronsList.sort((o1, o2) -> o2.getAbility().compareTo(o1.getAbility()));
                int count = 0;
                for (UserPatrons patrons : userPatronsList) {
                    if (count >= jobPatronsLimit) {
                        break;
                    }
                    Tomb.PartnerTemp.Builder builder = patronAbilityCorrection(patrons);
                    userAbilityTemp.setAbility(userAbilityTemp.getAbility() + builder.getBaseEarn());
                    count++;
                }
            }
            list.add(userAbilityTemp.build());
        }
        return list;
    }

    public static List<Long> getGroupUserList(int activityId, int groupId) {
        List<Long> userList = new ArrayList<>();
        UnionActivityGroup group = GameUnionActivityGroupMgr.getGroupData(activityId, groupId);
        if(group != null){
            for (Map.Entry<String, UnionActivityGroupUnion> unionEntry : group.getUnionDataMap().entrySet()) {
                for (Map.Entry<Long, UnionActivityGroupUser> userEntry : unionEntry.getValue().getUserMap().entrySet()) {
                    userList.add(userEntry.getKey());
                }
            }
        }
        return userList;
    }


    public static int findActivityUserNum(int activityId, int groupId) {
        int p1 = 10;
        long todayZeroTimeStamp = DateHelper.getTodayZeroTimeStamp();
        long t = todayZeroTimeStamp / 1000 - (long) p1 * 24 * 60 * 60;
        List<Long> userIdList = UserBussiness.getUserIdListByLastLoginTimeAndHasUnion(t);
        List<Long> groupUserList = getGroupUserList(activityId, groupId);
        if(userIdList.size() == 0){
            return userIdList.size();
        }else {
            userIdList.removeIf(aLong -> !groupUserList.contains(aLong));
        }
        return userIdList.size();
    }

    /**
     * 获取一下本区域最大进度值,用来更新商会成就进度值
     */
    public static int getMaxProgressByRepairZoneId(int zoneId) {
        int levelProgress = 0;
        int maxProgress = Integer.MAX_VALUE;
        for (ActivityTombRepair repair : config.getRepairs()) {
            if (zoneId == repair.getId()) {
                maxProgress = repair.getSchedule() - levelProgress;
                return maxProgress;
            } else {
                levelProgress = repair.getSchedule();
            }
        }
        return maxProgress;
    }

    /**
     * 同步商会修复进度
     */
    public static void updateAllMemberRepairCondition(List<Long> userIdList, Map<Integer, Long> progressMap) {
        List<ActivityConditionInfo> activityConditionInfoList = NormalActivityMgr.getActivityConditionInfoListByType(activityInfo.getActivityId(), eGamePlayerEventType.TombUnionNianTuNum.getValue());
        if (userIdList.isEmpty()) {
            return;
        }
        for (long userId : userIdList) {
            GamePlayer player = GamePlayerMgr.getOnlinePlayer(userId);
            if (player != null) {      //在线玩家
                player.notifyListener(eGamePlayerEventType.TombUnionNianTuNum.getValue(), progressMap);
            } else {                 //不在线玩家
                //拿出本次活动的玩家成就数据遍历
                List<UserActivityConditionData> allConditionData = UserActivityBussiness.getUserActivityConditionDataListByUserIdAndType(activityInfo.getActivityId(), userId, eGamePlayerEventType.TombUnionNianTuNum.getValue());
                for (UserActivityConditionData userActivityConditionData : allConditionData) {
                    //遍历活动成就配置
                    for (ActivityConditionInfo activityConditionInfo : activityConditionInfoList) {
                        if (activityConditionInfo.getConditionId() == userActivityConditionData.getConditionId()) {
                            int key = activityConditionInfo.getParamList().get(2).intValue();
                            userActivityConditionData.setValue(BigInteger.valueOf(progressMap.get(key)));
                            //马上入库掉
                            UserActivityBussiness.updateUserActivityConditionData(userActivityConditionData);
                            break;
                        }
                    }
                }

            }

        }

    }

    /**
     * 商会能否变化人员
     */
    public static boolean canChangeUnion() {
        long now = System.currentTimeMillis();
        if (activityInfo != null) {
            if (now > activityInfo.getBeginTime() * 1000L && now < activityInfo.getEndTime() * 1000L) {
                return false;
            }

        }
        return true;
    }

    /**
     * 是否是人偶道具
     */
    public static boolean isDollItem(int goodsId) {
        if (config != null && ActivityMgr.activityInShowTime(activityInfo)) {
            return config.getConfig().getTOMB_ALL_DOLL_ID_LIST().contains(goodsId);
        }
        return false;
    }


    public static Property getDisperseGoldReward(BigInteger earnSpeed) {
        RandomHelper r = new RandomHelper();

        List<Integer> tombSpreadWealthConfig = config.getConfig().getTOMB_SPREAD_WEALTH_CONFIG();

        //银两奖励
        int totalSilver = r.next(tombSpreadWealthConfig.get(0), tombSpreadWealthConfig.get(1));
        BigInteger silver = earnSpeed.multiply(BigInteger.valueOf(totalSilver));

        //元宝奖励
        int IngotsNum = r.next(tombSpreadWealthConfig.get(2), tombSpreadWealthConfig.get(3));

        Property property = new Property();
        property.addProperty(GameConfig.GAME_MONEY_SILVER, silver);
        property.addProperty(GameConfig.GAME_MONEY_INGOTS, BigInteger.valueOf(IngotsNum));
        return property;
    }

    public static List<Long> getServerIdSet(ActivityInfo activityInfo, int groupId){
        Map<Integer, UnionActivityGroup> groupMap = GameUnionActivityGroupMgr.getGroupMap(activityInfo.getActivityId());
        if(groupMap == null){
            return new ArrayList<>();
        }
        for (Map.Entry<Integer, UnionActivityGroup> groupEntry : groupMap.entrySet()) {
            if(groupEntry.getKey() != groupId){
                continue;
            }
            if(groupEntry.getValue().getServerSet().contains(GameServer.getInstance().getServerId())){
                return new ArrayList<>(groupEntry.getValue().getServerSet());
            }
        }
        return activityInfo.getServerIdList();
    }

    public static void initService(GameService syncMessageService) {
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_USER_PATRONS_INFO_CROSS_TO_GAME, new TombUserPatronsInfoServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_USER_TOP_PATRONS_CROSS_TO_GAME, new TombUserTopPatronsServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_EVENT_INFO_NOTIFY_CROSS_TO_GAME, new TombEventInfoNotifyServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_MAZE_ALLY_MOVE_NOTIFY_CROSS_TO_GAME, new TombMazeAllyMoveNotifyServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_EVENT_SYNC_PUSH, new TombEventSyncServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_EVENT_BATTLE_SYNC_PUSH, new TombEventBattleSyncServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_USER_UNDER_ATTACK_PUSH, new TombUserUnderAttackPushServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_BOSS_GO_DOWNSTAIRS_PUSH, new TombBossGoDownstairsPushServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_ELITE_NPC_INFO_PUSH, new TombEliteNpcInfoPushServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_UNION_IN_TRAP_SAVE_PUSH, new TombUnionInTrapHelpPushServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_USER_ADD_ITEM_CROSS_TO_GAME, new TombUserAddItemServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_SERVER_TOP_PATRONS_CROSS_TO_GAME, new TombServerTopPatronsServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_USER_COST_ITEM_CROSS_TO_GAME, new TombUserCostItemServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_SERVER_DATA_CROSS_TO_GAME, new TombServerDataServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_LOG_CROSS_TO_GAME, new TombUserLogServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_USER_SCORE_CHANGE_CROSS_TO_GAME, new TombUserChangeScoreServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_NOTIFY_PUSH, new TombNotifyPushServiceCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_TOMB_NPC_INFO_PUSH, new TombNpcInfoPushServiceCmd());
    }

}
